<template>
  <div id="iconSelectView">
    <!--    popper-class引用的属性必须为公共的class样式才能生效，不能放在scoped中-->
    <el-popover
      ref="popoverRef"
      placement="bottom-start"
      popper-class="el-popper-icon-select-class"
      :width="340"
      trigger="click"
      @before-enter="showIconSelect"
      @before-leave="hideIconSelect"
    >
      <template #reference>
        <!--        :suffix-icon="selectOption!=''?'CircleClose':iconSelectVisible?'ArrowDown':'ArrowUp'"-->
        <el-input placeholder="请选择图标" readonly v-model="selectOption" select :style="{ width: selectWidth }">
          <template #suffix>
            <el-icon v-if="selectOption !== null && selectOption !== ''" @click="clearValue" class="el-input__icon" style="cursor: pointer"
              ><CircleClose
            /></el-icon>
            <el-icon v-else class="el-input__icon">
              <ArrowDown v-if="iconSelectVisible" />
              <ArrowUp v-else />
            </el-icon>
          </template>
        </el-input>
      </template>
      <div id="option-body">
        <el-tabs v-model="activeTabName">
          <el-tab-pane name="baseIcon">
            <template #label> 基本图标 </template>
            <el-row :gutter="5" justify="start" align="middle" style="width: 300px; height: 100%">
              <el-col :span="4" v-for="icon in filteredIconList" :key="icon" class="grid-col">
                <el-tooltip :content="icon.name" placement="bottom" effect="light" :offset="0" :hide-after="0" :show-after="500">
                  <el-card
                    shadow="hover"
                    @mouseover="changeIconSize(icon, iconSizeOfBig)"
                    @mouseout="changeIconSize(icon, iconSizeOfNormal)"
                    @click="selectIcon(icon.name)"
                  >
                    <el-icon :size="icon.iconSize"><component class="icon" :is="icon.name" /></el-icon>
                  </el-card>
                </el-tooltip>
              </el-col>
            </el-row>
            <!-- <el-row :gutter="5" justify="start" align="middle">
              <el-col :span="12" class="grid-col"><el-button>上一页</el-button></el-col>
              <el-col :span="12" class="grid-col"><el-button>下一页</el-button></el-col>
            </el-row> -->
          </el-tab-pane>
        </el-tabs>
        <div id="search-input">
          <el-input clearable v-model="searchIcon" placeholder="搜索图标" suffix-icon="Search" @input="filterIcons" />
        </div>
      </div>
    </el-popover>
  </div>
</template>

<script lang="ts" setup>
// 图标选择列表
import { ref, onMounted, computed, withDefaults, defineProps, watch, nextTick } from 'vue';
import { ElPopover } from 'element-plus';
import * as Icons from '@element-plus/icons-vue';

import { defineEmits } from 'vue';
const emit = defineEmits(['update:modelValue']);

interface Props {
  modelValue: any; // 获取从父组件input类型绑定的值,vue3中使用了modelValue来替代value，并且传递过来的是非ref或reactive类型的值,input方法了改成update:modelValue
  clickAndCloseDialog?: boolean; // 是否点击图标后就关闭对话框
  selectWidth?: string; //下拉框宽度
}
const props = withDefaults(defineProps<Props>(), {
  modelValue: () => '',
  clickAndCloseDialog: true,
  selectWidth: '240px'
});
// 定义弹出框的ref对象，定义目的用于手动控制关闭
const popoverRef = ref<InstanceType<typeof ElPopover>>();
const iconSelectVisible = ref<boolean>(); // 是否显示下拉框下拉箭头的变量
// const selectOption = ref<string>(''); // 文本框的值
const searchIcon = ref<string>(''); // 搜索框的值
const iconSizeOfBig = 32; // 大图标的尺寸
const iconSizeOfNormal = 20; // 图标的正常尺寸
// tab名称
const activeTabName = ref('baseIcon');
// 与父组件v-model绑定的值进行关联
const selectOption = computed({
  // 要转化为ref对象
  get() {
    // 当父组件的值改变时触发
    return props.modelValue;
  },
  set(val) {
    // 当本组件的值改变时触发
    // 将本组件的值传给父组件
    emit('update:modelValue', val);
  }
});
// 定义图标类
class Icon {
  name: string;
  iconSize: number;
  constructor(name: string, size: number) {
    this.name = name;
    this.iconSize = size;
  }
}
// 定义图标列表
// 获取element plus的所有图标
const allIcons = Object.keys(Icons);
//初始化图标
const initialIcons = ref<Icon[]>([]);
//过滤后显示的图标
const filteredIconList = ref<Icon[]>([]);
// 组件初始化时获取图标对象，20250417最后优化
onMounted(() => {
  // 初始化时加载部分图标// 加载初始化的个图标
  allIcons.slice(0, 36).forEach((key) => {
    initialIcons.value.push(new Icon(key, iconSizeOfNormal));
  });
  // filteredIconList.value = initialIcons.value;
});
// 根据用户输入动态加载更多图标
const filterIcons = () => {
  console.log('查询', searchIcon.value);
  if (searchIcon.value === '') {
    filteredIconList.value = initialIcons.value;
  } else {
    //根据搜索中的用户名显示相应图标
    const filteredIcons = allIcons.filter((iconName) => iconName.toLowerCase().includes(searchIcon.value.toLowerCase()));
    filteredIconList.value = filteredIcons.map((name) => new Icon(name, iconSizeOfNormal));
  }
  console.log(filteredIconList.value);
  // 确保视图刷新
  // nextTick(() => {
  //   console.log('视图已刷新');
  // });
};
// 当鼠标经过图标，图标大小的变化
const changeIconSize = (icon: Icon, size: number) => {
  // 第一个参数：图像对象；第二个参数：要改变的图标大小
  // eslint-disable-next-line no-param-reassign
  icon.iconSize = size;
};
// 模拟下拉框选择
const showIconSelect = () => {
  // 显示下拉框
  iconSelectVisible.value = true;
};
const hideIconSelect = () => {
  // 隐藏下拉框
  iconSelectVisible.value = false;
  // 清空搜索框的值
};
// 当点击下拉框中的图标时，为文本框赋值图标的名称
const selectIcon = (name: string) => {
  selectOption.value = name;
  if (props.clickAndCloseDialog) {
    // 点击就关闭弹框。注意，这个hide方法在el-popover组件中没有提示，但是可以关闭弹框
    popoverRef.value!.hide();
    // eslint-disable-next-line no-unused-expressions
    // unref(popoverRef).popperRef?.doClose?.();
  }
};
// 清空文本框的值
const clearValue = () => {
  selectOption.value = '';
  // 后续加上阻止下拉框状态改变代码，让体验更合适
};
// 搜索框的值,默认打开的时候与传入的文本框值绑定。这样处理诸如编辑表单的业务时，可以直接显示当前的图标。
watch(
  () => props.modelValue,
  (newValue) => {
    console.log('变化');
    searchIcon.value = newValue;
    filterIcons();
  },
  { immediate: true }
);
</script>

<style lang="scss" scoped>
#iconSelectView {
}
#option-body {
  /*下拉框主体部分*/
  position: relative;
  #search-input {
    /*搜索文本框*/
    position: absolute;
    width: 120px;
    right: 10px;
    top: 1px;
  }
  .grid-col {
    height: 50px;
    padding: 2px;
    /*设置水平垂直居中*/
    display: flex;
    justify-content: center;
    align-items: center;
    /*设置边框*/
    //border: 1px solid #ededed;
    color: #606266;
    /*text-align:center;*/
    font-size: 12px;
    :deep(.el-card) {
      width: 100%;
      height: 100%;
      /*设置水平垂直居中，这样el-card__body才能居中*/
      display: flex;
      justify-content: center;
      align-items: center;
      .el-card__body {
        /*设置水平垂直居中,这样里面的图标才能居中*/
        display: flex;
        justify-content: center;
        align-items: center;
      }
    }
  }
}
</style>
